package com.mano.mall.service.callback.template;

import com.alibaba.fastjson.JSONObject;
import com.mano.mall.service.constant.PayConstant;
import com.mano.mall.service.domain.PayMQMsg;
import com.mano.mall.service.mapper.PaymentTransactionLogMapper;
import com.mano.mall.service.mapper.PaymentTransactionMapper;
import com.mano.mall.service.mapper.entity.PaymentTransactionEntity;
import com.mano.mall.service.mapper.entity.PaymentTransactionLogEntity;
import com.mano.mall.service.mq.producer.IntegralProducer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * 使用模版方法重构异步回调代码
 */
@Slf4j
@Component
public abstract class AbstractPayCallbackTemplate {

	@Autowired
	private PaymentTransactionLogMapper paymentTransactionLogMapper;

	@Autowired
	private PaymentTransactionMapper paymentTransactionMapper;

	@Autowired
	private IntegralProducer integralProducer;

	// TODO bean的name 和 注入的名字 的关系？
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;

	/**
	 * 异步回调验证签名参数
	 * 
	 * @param req
	 * @param resp
	 * @return
	 */
	public abstract Map<String, String> verifySignature(HttpServletRequest req, HttpServletResponse resp);

	/**
	 * 异步回调执行业务逻辑
	 *
	 * @return
	 */
	public abstract String asyncService(Map<String, String> verifySignature);

	/**
	 * 失败结果
	 * 
	 * @return
	 */
	public abstract String failResult();

	/**
	 * 成功结果
	 * 
	 * @return
	 */
	public abstract String successResult();

	/**
	 *  处理 支付完成后的MQ操作
	 *  必须加 @Async 异步操作
	 *  TODO 增加积分
	 *  TODO 通知卖家
	 */
	@Async
	public void handlerMqMSg(String paymentId){
		// 1. 获取支付消息
		PaymentTransactionEntity paymentTransaction = paymentTransactionMapper.selectByPaymentId(paymentId);

		// 2. 增加积分
//		PayMQMsg payMQMsg = new PayMQMsg();
//		payMQMsg.setUserId(paymentTransaction.getUserId());
//		payMQMsg.setPaymentId(paymentTransaction.getPaymentId());
//		payMQMsg.setIntegral(100);
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("paymentId", paymentTransaction.getPaymentId());
		jsonObject.put("userId", paymentTransaction.getUserId());
		jsonObject.put("integral", 100);
		integralProducer.send(jsonObject);

		// 3.TODO 通知卖家接单处理
	}

	public String asyncCallBack(HttpServletRequest req, HttpServletResponse resp) {
		// 1.获取第三方支付回调参数信息
		Map<String, String> verifySignature = verifySignature(req, resp);

		// 2.将日志根据支付id存放到数据库中
		String paymentId = verifySignature.get("paymentId");
		if (StringUtils.isEmpty(paymentId)) {
			return failResult();
		}
		log.info(">>>service-1");
		// 异步写入日志
		taskExecutor.execute(new LogThread(paymentId,verifySignature));

		if (verifySignature.get(PayConstant.RESULT_NAME).equals(PayConstant.RESULT_PAYCODE_201)) {
			return failResult();
		}
		// 2.将支付参数信息根据支付id插入到数据库中
//		payLog(verifySignature);

		// 3.处理异步回调相关日志信息
		String respStr = asyncService(verifySignature);

		// TODO 处理MQ消息
		handlerMqMSg(paymentId);
		return respStr;
	}

	/**
	 * 将log写入到日志中
	 * 这里最好不用直接处理
	 * 采用多线程 @Sync
	 * 或者使用MQ异步写到数据库中
	 * 
	 * @param paymentParameter
	 */
	private void payLog(String paymentId,Map<String, String> paymentParameter) {
		log.info(">>paymentId:{paymentId},verifySignature:{}", paymentParameter);
		PaymentTransactionLogEntity paymentTransactionLogEntity = new PaymentTransactionLogEntity();
		paymentTransactionLogEntity.setAsyncLog(paymentParameter.toString());
		paymentTransactionLogEntity.setTransactionId(paymentId);
		paymentTransactionLogMapper.insertTransactionLog(paymentTransactionLogEntity);

	}


	class LogThread implements Runnable {
		private String paymentId;
		private Map<String, String> verifySignature;

		public LogThread(String paymentId, Map<String, String> verifySignature) {
			this.paymentId = paymentId;
			this.verifySignature = verifySignature;
		}

		@Override
		public void run() {
			log.info(">>>>异步线程开始...service-2");
			payLog(paymentId, verifySignature);
			log.info(">>>>异步线程结束...service-3");
		}

	}


}
